package com.poem.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.poem.context.BaseContext;
import com.poem.dto.*;
import com.poem.constant.MessageConstant;
import com.poem.entity.Authors;
import com.poem.entity.Favorites;
import com.poem.entity.Poems;
import com.poem.exception.BaseException;
import com.poem.mapper.AuthorsMapper;
import com.poem.mapper.FavoritesMapper;
import com.poem.mapper.PoemsMapper;
import com.poem.result.PageResult;
import com.poem.service.FavoritesService;
import com.poem.vo.FavoritesPageWithAdmin;
import com.poem.vo.FavoritesWithPoemsOrTypes;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: FavoritesServiceImpl
 * @Author: YLY
 * @Description:
 * @Date: 2025/10/30
 * @Version: 1.0
 */
@Service
public class FavoritesServiceImpl implements FavoritesService {

    @Resource
    private FavoritesMapper favoritesMapper;
    @Resource
    private PoemsMapper poemsMapper;
    @Resource
    private AuthorsMapper authorsMapper;

    /**
     * 检查收藏
     * 
     * @param resourceType
     * @param resourceId
     * @return
     */
    public boolean checkFavorite(String resourceType, Long resourceId) {

        Favorites favorites = new Favorites();
        // 获得当前userId
        Long currentId = BaseContext.getCurrentId();
        favorites.setUserId(currentId);
        favorites.setResourceId(resourceId);
        favorites.setResourceType(resourceType);

        List<Favorites> favoritesList = favoritesMapper.list(favorites);
        if (!favoritesList.isEmpty()) {
            return true;
        } else
            return false;

    }

    /**
     * 批量检查收藏
     * 
     * @param favoritesCheckDTO
     * @return
     */
    public Map<Long, Boolean> batchCheckFavorite(FavoritesCheckDTO favoritesCheckDTO) {
        Map<Long, Boolean> result = new HashMap<>();
        List<Long> resourceIds = favoritesCheckDTO.getResourceIds();
        String resourceType = favoritesCheckDTO.getResourceType();
        Long userId = BaseContext.getCurrentId();
        for (Long resourceId : resourceIds) {
            boolean isFavorite = favoritesMapper.checkFavorite(resourceType, resourceId, userId);
            result.put(resourceId, isFavorite);
        }
        return result;
    }

    /**
     * 添加收藏
     * 
     * @param favoritesAddDTO
     */
    public void addFavorites(FavoritesAddDTO favoritesAddDTO) {
        // 检查是否已收藏
        if (checkFavorite(favoritesAddDTO.getResourceType(), favoritesAddDTO.getResourceId())) {
            throw new BaseException(MessageConstant.FAVORITE_ALREADY_EXISTS);
        }

        // 检查资源是否存在
        if ("poem".equals(favoritesAddDTO.getResourceType())) {
            Poems poem = poemsMapper.getById(favoritesAddDTO.getResourceId());
            if (poem == null) {
                throw new BaseException(MessageConstant.RESOURCE_NOT_EXISTS);
            }
        } else if ("author".equals(favoritesAddDTO.getResourceType())) {
            Authors author = authorsMapper.getById(favoritesAddDTO.getResourceId());
            if (author == null) {
                throw new BaseException(MessageConstant.RESOURCE_NOT_EXISTS);
            }
        }

        Favorites favorites = new Favorites();
        favorites.setUserId(BaseContext.getCurrentId());
        BeanUtils.copyProperties(favoritesAddDTO, favorites);
        favoritesMapper.addFavorites(favorites);
    }

    public void deleteFavorites(FavoritesDTO favoritesDTO) {
        // 检查收藏是否存在
        if (!checkFavorite(favoritesDTO.getResourceType(), favoritesDTO.getResourceId())) {
            throw new BaseException(MessageConstant.FAVORITE_NOT_EXISTS);
        }

        Favorites favorites = new Favorites();
        favorites.setUserId(BaseContext.getCurrentId());
        favorites.setResourceId(favoritesDTO.getResourceId());
        favorites.setResourceType(favoritesDTO.getResourceType());

        favoritesMapper.deleteFavorites(favorites);
    }

    public PageResult<FavoritesWithPoemsOrTypes> pageQuery(FavoritesPageQueryDTO favoritesPageQueryDTO) {
        // 开启分页（作用于后续第一个MyBatis查询）
        PageHelper.startPage(favoritesPageQueryDTO.getPage(), favoritesPageQueryDTO.getPageSize());

        // 设置当前用户ID（权限控制，普通用户只能查询自己的收藏）
        Long userId = BaseContext.getCurrentId();
        favoritesPageQueryDTO.setUserId(userId);

        // 第一步：获取收藏信息列表（包含resourceId和createTime），分页会自动应用
        // 支持动态查询：resourceType、title（诗文标题）、name（作者姓名，可用于筛选收藏的作者或诗文的作者）
        List<Map<String, Object>> favoritesList = favoritesMapper.getFavorites(favoritesPageQueryDTO);

        // 如果没有收藏记录，直接返回空结果
        if (favoritesList.isEmpty()) {
            Page<Map<String, Object>> page = (Page<Map<String, Object>>) favoritesList;
            return new PageResult<>(page.getTotal(), new ArrayList<>());
        }

        // 第二步：提取所有的resourceId，并建立resourceId到createTime的映射
        List<Long> resourceIds = new ArrayList<>();
        Map<Long, LocalDateTime> resourceIdToCreateTimeMap = new HashMap<>();

        for (Map<String, Object> item : favoritesList) {
            Long resourceId = ((Number) item.get("resourceId")).longValue();
            LocalDateTime createTime = (LocalDateTime) item.get("createTime");
            resourceIds.add(resourceId);
            resourceIdToCreateTimeMap.put(resourceId, createTime);
        }

        // 第三步：根据resourceType批量查询资源（poems或authors）
        List<FavoritesWithPoemsOrTypes> result = new ArrayList<>();

        if ("poem".equals(favoritesPageQueryDTO.getResourceType())) {
            // 批量查询诗文数据
            List<Poems> poemsList = poemsMapper.getPoems(resourceIds);

            // 第四步：组装结果，将收藏时间赋值给每个结果对象
            for (Poems poem : poemsList) {
                FavoritesWithPoemsOrTypes vo = new FavoritesWithPoemsOrTypes();
                vo.setResource(poem);
                vo.setCreateTime(resourceIdToCreateTimeMap.get(poem.getId()));
                result.add(vo);
            }
        } else if ("author".equals(favoritesPageQueryDTO.getResourceType())) {
            // 批量查询作者数据
            List<Authors> authorsList = authorsMapper.getAuthors(resourceIds);

            // 第四步：组装结果，将收藏时间赋值给每个结果对象
            for (Authors author : authorsList) {
                FavoritesWithPoemsOrTypes vo = new FavoritesWithPoemsOrTypes();
                vo.setResource(author);
                vo.setCreateTime(resourceIdToCreateTimeMap.get(author.getId()));
                result.add(vo);
            }
        }

        // 获取分页信息（从Page对象中获取总数）
        Page<Map<String, Object>> page = (Page<Map<String, Object>>) favoritesList;
        return new PageResult<>(page.getTotal(), result);
    }

    /**
     * 批量统计收藏数量
     *
     * @param favoritesCountDTO
     * @return
     */
    public Map<Long, Integer> batchCount(FavoritesCountDTO favoritesCountDTO) {

        // 1. 根据资源类型进行分类
        String resourceType = favoritesCountDTO.getResourceType();

        // 2. 然后通过map映射，键为resourceId，值为收藏数量
        Map<Long, Integer> countMap = new HashMap<>();

        List<Long> resourceIds = new ArrayList<>(favoritesCountDTO.getResourceIds());

        for (Long resourceId : resourceIds) {

            Integer count = favoritesMapper.countById(resourceType, resourceId);
            countMap.put(resourceId, count);
        }

        // 3. 返回结果
        return countMap;

    }

    /**
     * 管理员查询所有不同用户的收藏诗文或作者
     *
     * @param favoritesPageQueryDTO
     * @return
     */
    public PageResult<FavoritesPageWithAdmin> pageQueryWithAdmin(FavoritesPageQueryDTO favoritesPageQueryDTO) {
        // 开启分页（作用于后续第一个MyBatis查询）
        PageHelper.startPage(favoritesPageQueryDTO.getPage(), favoritesPageQueryDTO.getPageSize());

        // 第一步：获取收藏信息列表（包含resourceId、createTime和username），分页会自动应用
        // 支持动态查询：resourceType、userId（可选）、username（用户名）、title（诗文标题）、name（作者姓名，可用于筛选收藏的作者或诗文的作者）
        List<Map<String, Object>> favoritesList = favoritesMapper.getFavoritesWithAdmin(favoritesPageQueryDTO);

        // 如果没有收藏记录，直接返回空结果
        if (favoritesList.isEmpty()) {
            Page<Map<String, Object>> page = (Page<Map<String, Object>>) favoritesList;
            return new PageResult<>(page.getTotal(), new ArrayList<>());
        }

        // 第二步：提取所有的resourceId（去重，用于批量查询资源）
        List<Long> resourceIds = new ArrayList<>();
        for (Map<String, Object> item : favoritesList) {
            Long resourceId = ((Number) item.get("resourceId")).longValue();
            if (!resourceIds.contains(resourceId)) {
                resourceIds.add(resourceId);
            }
        }

        // 第三步：批量查询资源（poems或authors），建立resourceId到资源的映射
        Map<Long, Object> resourceIdToResourceMap = new HashMap<>();
        if ("poem".equals(favoritesPageQueryDTO.getResourceType())) {
            // 批量查询诗文数据
            List<Poems> poemsList = poemsMapper.getPoems(resourceIds);
            for (Poems poem : poemsList) {
                resourceIdToResourceMap.put(poem.getId(), poem);
            }
        } else if ("author".equals(favoritesPageQueryDTO.getResourceType())) {
            // 批量查询作者数据
            List<Authors> authorsList = authorsMapper.getAuthors(resourceIds);
            for (Authors author : authorsList) {
                resourceIdToResourceMap.put(author.getId(), author);
            }
        }

        // 第四步：遍历原始查询结果，组装返回对象（确保每条收藏记录都正确匹配）
        List<FavoritesPageWithAdmin> result = new ArrayList<>();
        for (Map<String, Object> item : favoritesList) {
            Long resourceId = ((Number) item.get("resourceId")).longValue();
            LocalDateTime createTime = (LocalDateTime) item.get("createTime");
            String itemUsername = ((String) item.get("username"));

            // 从映射中获取资源信息
            Object resource = resourceIdToResourceMap.get(resourceId);
            if (resource != null) {
                FavoritesPageWithAdmin vo = new FavoritesPageWithAdmin();
                vo.setResource(resource);
                vo.setCreateTime(createTime);
                vo.setUsername(itemUsername);
                result.add(vo);
            }
        }

        // 获取分页信息（从Page对象中获取总数）
        Page<Map<String, Object>> page = (Page<Map<String, Object>>) favoritesList;
        return new PageResult<>(page.getTotal(), result);
    }
}